package org.sraosha.microservice.gateway.filter;

import org.sraosha.framework.constants.RedisStorage;
import org.sraosha.microservice.gateway.constants.RedisKey;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.HttpHeaders;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.util.List;

/**
 * 1.允许访问的路径，直接放行
 * 2.header中必须有token，并且在redis中存在
 * 3.header中必须有authorization，并且在redis中存在
 */
@Component
@Slf4j
public class UaFilter extends AbstractFilter implements GlobalFilter, Ordered {

    /**
     * 判断当前路径是否需要过滤器处理
     * @param exchange
     * @param chain
     * @return
     */
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        return super.handle("sraosha", exchange, chain);
    }

    @Override
    public Boolean checkAllowPathList(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();
        List<String> allowPathList = filterParamValue.getOauth2AllowPathList();
        if (null != allowPathList && allowPathList.size() != 0) {
            String path = request.getPath().toString();
            if (allowPathList.contains(path)) {
                log.info("接口{}是允许直接访问的接口，直接放行", path);
                return true;
            }
        }
        return false;
    }

    /**
     * header中必须有token，并且在redis中存在
     * @param exchange
     * @param chain
     * @return
     */
    @Override
    public Boolean checkToken(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();
        HttpHeaders httpHeaders = request.getHeaders();
        List<String> tokenList = httpHeaders.get("token");
        if (null != tokenList && tokenList.size() > 0){
            Boolean hasTokenInRedis = false;
            String tokenInHeader = null;
            for (int i = 0; i<tokenList.size(); i++){
                tokenInHeader = tokenList.get(i);
                // 从redis获取用户信息
                StringBuffer key = new StringBuffer().append(RedisKey.SRAOSHA_WEB).append(RedisStorage.COLON).append(RedisKey.SRAOSHA_WEB)
                        .append(RedisStorage.COLON).append(RedisStorage.TOKEN_PREFIX)
                        .append(tokenInHeader);
                String tokenInRedis = String.valueOf(redisManager.get(key.toString()));
                if (null != tokenInRedis){
                    hasTokenInRedis = true;
                    break;
                }
            }
            if (!hasTokenInRedis){
                log.warn("header中的token为【{}】，但是在redis中没有对应的token", tokenInHeader);
                return false;
            }
        } else {
            log.warn("header中没有token");
            return false;
        }
        return true;
    }

    /**
     * header中必须有authorization，并且在redis中存在
     * @param exchange
     * @param chain
     * @return
     */
    @Override
    public Boolean checkClient(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();
        HttpHeaders httpHeaders = request.getHeaders();
        List<String> authorizationInHeaderList = httpHeaders.get("authorization");
        if (null == authorizationInHeaderList || authorizationInHeaderList.size() == 0) {
            log.warn("header中没有authorization");
            return false;
        }

        // 从redis获取sraosha:sraosha:ua-client
        StringBuffer key = new StringBuffer().append(RedisKey.SRAOSHA_WEB).append(RedisStorage.COLON).append(RedisKey.SRAOSHA_WEB)
                .append(RedisStorage.COLON).append(RedisKey.CLIENT);
        String authorizationInRedisString = String.valueOf(redisManager.get(key.toString()));
        JSONArray authorizationInRedisJsonArray = JSONObject.parseArray(authorizationInRedisString);
        if (null == authorizationInRedisJsonArray || authorizationInRedisJsonArray.size() == 0) {
            log.warn("redis中没有{}", key);
            return false;
        }

        Boolean authorizationIsSame = false;
        String authorizationInHeader = null;
        String authorizationInRedis = null;
        for (int i = 0; i < authorizationInHeaderList.size(); i++) {
            authorizationInHeader = authorizationInHeaderList.get(i);
            for (int j = 0; j < authorizationInRedisJsonArray.size(); j++) {
                JSONObject authorizationInRedisJsonObject = (JSONObject) authorizationInRedisJsonArray.get(j);
                authorizationInRedis = authorizationInRedisJsonObject.getString("authorization");
                if (authorizationInHeader.equals(authorizationInRedis)) {
                    authorizationIsSame = true;
                    break;
                }
            }
            if (authorizationIsSame) {
                break;
            }
        }
        if (!authorizationIsSame) {
            log.warn("header中的authorization{}和redis中的authorization不同", authorizationInHeader, authorizationInRedis);
            return false;
        }
        return true;
    }

    @Override
    public int getOrder() {
        return 0;
    }
}
